package cn.anecansaitin.whimsy.client.listener;

import cn.anecansaitin.whimsy.Whimsy;
import cn.anecansaitin.whimsy.client.event.MouseMoveEvent;
import cn.anecansaitin.whimsy.client.event.PreKeyInputEvent;
import cn.anecansaitin.whimsy.common.attachment.DoomfistSkill;
import cn.anecansaitin.whimsy.common.capabilities.battle.IBattleController;
import cn.anecansaitin.whimsy.common.capabilities.battle.IBattleMode;
import cn.anecansaitin.whimsy.common.network.KeyInputPack;
import cn.anecansaitin.whimsy.common.network.NetworkHelper;
import cn.anecansaitin.whimsy.common.network.RockSceptreKeyInput;
import cn.anecansaitin.whimsy.common.register.ModDataAttachments;
import cn.anecansaitin.whimsy.common.register.ModEffects;
import cn.anecansaitin.whimsy.common.register.ModItems;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod;
import net.neoforged.neoforge.client.event.InputEvent;
import org.lwjgl.glfw.GLFW;

@Mod.EventBusSubscriber(modid = Whimsy.MODID, value = Dist.CLIENT)
public class KeyInputEvent {
    @SubscribeEvent
    public static void mouseButtonInput(InputEvent.MouseButton.Pre event) {
        Minecraft mc = Minecraft.getInstance();

        if (mc.player == null || mc.screen != null) {
            return;
        }

        rockSceptreMouse(event);

        if (doomFistInput(event.getButton(), event.getAction(), event.getModifiers())) {
            event.setCanceled(true);
        }
    }

    @SubscribeEvent
    public static void keyInput(PreKeyInputEvent event) {
        if (Minecraft.getInstance().player == null) {
            return;
        }

//        doomFistKey(event);
        if (doomFistInput(event.getKey(), event.getAction(), event.getModifiers())) {
            event.setCanceled(true);
        }
    }

    private static boolean doomFistInput(int key, int action, int modifiers) {
        LocalPlayer player = Minecraft.getInstance().player;
        IBattleMode battleMode = player.getCapability(IBattleMode.BATTLE_MODE);

        if (!battleMode.isInMode()) {
            return false;
        }

        IBattleController controller = battleMode.getController();

        if (controller == null) {
            return false;
        }

        byte[] bytes = controller.keyInput(player, key, action, modifiers);

        //判断是否需要发包
        if (bytes[0] == (byte) 1) {
            controller.sendKeyToServer(player, key, action, modifiers);
        }

        return bytes[1] == (byte) 1;
    }

    private static void rockSceptreMouse(InputEvent.MouseButton.Pre event) {
        if (Minecraft.getInstance().player.getMainHandItem().is(ModItems.ROCK_SCEPTRE.get())) {
            int button = event.getButton();
            int action = event.getAction();

            if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && action == 1) {
                RockSceptreKeyInput keyInput = new RockSceptreKeyInput(true, false);
                NetworkHelper.toServerPlayer(keyInput);
            }
        }
    }

    private static void doomFistMouse(InputEvent.MouseButton.Pre event) {
        LocalPlayer player = Minecraft.getInstance().player;
        ItemStack doomfist = player.getMainHandItem();
        DoomfistSkill skill = null;

        if (doomfist.is(ModItems.DOOMFIST.get())) {
            skill = doomfist.getData(ModDataAttachments.DOOMFIST_SKILL);

            switch (event.getButton()) {
                case GLFW.GLFW_MOUSE_BUTTON_LEFT -> {
                    if (event.getAction() != InputConstants.PRESS) {
                        break;
                    }

                    if (skill.rocketPunch.isCharging) {//如果右键在蓄力，则停止蓄力
                        NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.DOOMFIST, new int[]{GLFW.GLFW_MOUSE_BUTTON_LEFT, InputConstants.PRESS}));
                        event.setCanceled(true);
                        return;
                    } else if (skill.seismicSlam.isCasting) {//如果在释放裂地重拳，则什么都不做
                        event.setCanceled(true);
                        return;
                    } else if (skill.powerBlock.isCasting) {//如果在释放格挡，则取消格挡，并可以进行左键攻击
                        NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.DOOMFIST, new int[]{GLFW.GLFW_MOUSE_BUTTON_LEFT, InputConstants.PRESS}));
                    }
                }
                case GLFW.GLFW_MOUSE_BUTTON_RIGHT -> {//右击蓄力火箭重拳
                    if (event.getAction() != InputConstants.REPEAT && !skill.seismicSlam.isCasting) {
                        NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.DOOMFIST, new int[]{GLFW.GLFW_MOUSE_BUTTON_RIGHT, event.getAction()}));
                    }

                    event.setCanceled(true);
                    return;
                }
            }
        }

        if (player.getOffhandItem().is(ModItems.HAND_CANNON.get()) && event.getAction() == InputConstants.PRESS) {
            int[] keyInput = null;

            switch (event.getButton()) {
                case GLFW.GLFW_MOUSE_BUTTON_LEFT -> keyInput = new int[]{GLFW.GLFW_MOUSE_BUTTON_LEFT};
                case GLFW.GLFW_MOUSE_BUTTON_5 -> {
                    if (skill != null && (skill.seismicSlam.isCasting || skill.rocketPunch.isCasting || skill.powerBlock.isCasting)) {
                        break;//有在释放技能就不要进行近战攻击了
                    }

                    keyInput = new int[]{GLFW.GLFW_MOUSE_BUTTON_5};
                }
            }

            if (keyInput != null) {
                NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.HAND_CANNON, keyInput));
                event.setCanceled(true);
            }
        }
    }

    private static void effectMouse(InputEvent.MouseButton.Pre event) {
        LocalPlayer player = Minecraft.getInstance().player;

        if (player.hasEffect(ModEffects.STUN.get())) {
            event.setCanceled(true);
            return;
        }

        if (player.hasEffect(ModEffects.ROCKET_PUNCH.get())) {
            event.setCanceled(true);
        }
    }

    @SubscribeEvent
    public static void mouseMoveInput(MouseMoveEvent event) {
        LocalPlayer player = Minecraft.getInstance().player;
        event.setCanceled(player.hasEffect(ModEffects.STUN.get())
                || player.hasEffect(ModEffects.ROCKET_PUNCH.get()));
    }

    public static void doomFistKey(PreKeyInputEvent event) {
        LocalPlayer player = Minecraft.getInstance().player;
        DoomfistSkill skill = null;

        if (player.getMainHandItem().is(ModItems.DOOMFIST.get())) {
            skill = player.getMainHandItem().getData(ModDataAttachments.DOOMFIST_SKILL);

            switch (event.getKey()) {
                case GLFW.GLFW_KEY_SPACE -> {
                    if (event.getAction() != InputConstants.PRESS) {
                        return;
                    }

                    boolean removed = player.removeEffect(ModEffects.ROCKET_PUNCH.get());
                    //因为玩家移动是以客户端为准，因此，直接在客户端施加效果
                    if (removed) {
                        Vec3 deltaMovement = player.getViewVector(1).multiply(1, 0, 1).normalize().scale(2).add(0, 0.5, 0);
                        player.setDeltaMovement(deltaMovement);
                        NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.DOOMFIST, new int[]{GLFW.GLFW_KEY_SPACE, InputConstants.PRESS}));
                        event.setCanceled(true);
                    }
                }
                case GLFW.GLFW_KEY_E -> {
                    if (event.getAction() != InputConstants.PRESS) {
                        event.setCanceled(true);
                        return;
                    }

                    if (skill.seismicSlam.tryUse()) {
                        float xRot = player.getViewXRot(1);

                        if (xRot > -15) {
                            xRot = -10;
                        } else if (xRot < -80) {
                            xRot = -75;
                        }

                        float f = xRot * (float) (Math.PI / 180.0);
                        float f1 = -player.getViewYRot(1) * (float) (Math.PI / 180.0);
                        float f2 = Mth.cos(f1);
                        float f3 = Mth.sin(f1);
                        float f4 = Mth.cos(f);
                        float f5 = Mth.sin(f);
                        Vec3 deltaMovement = new Vec3(f3 * f4, -f5, f2 * f4).normalize().scale(2);

                        player.setDeltaMovement(deltaMovement);
                        NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.DOOMFIST, new int[]{GLFW.GLFW_KEY_E, InputConstants.PRESS}));
                    } else if (skill.seismicSlam.isCasting) {
                        NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.DOOMFIST, new int[]{GLFW.GLFW_KEY_E, InputConstants.PRESS}));
                    }

                    event.setCanceled(true);
                }
                case GLFW.GLFW_KEY_LEFT_SHIFT -> {
                    if (event.getAction() == InputConstants.PRESS && ((skill.powerBlock.tryUse() && !skill.rocketPunch.isCasting && !skill.seismicSlam.isCasting) || skill.powerBlock.isCasting)) {
                        NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.DOOMFIST, new int[]{GLFW.GLFW_KEY_LEFT_SHIFT, InputConstants.PRESS}));
                    }

                    event.setCanceled(true);
                }
            }
        }

        if (player.getOffhandItem().is(ModItems.HAND_CANNON.get())) {
            switch (event.getKey()) {
                case GLFW.GLFW_KEY_V -> {//近战攻击
                    if (skill != null) {
                        if (event.getAction() == InputConstants.PRESS && !skill.seismicSlam.isCasting && !skill.rocketPunch.isCasting && !skill.powerBlock.isCasting) {
                            NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.HAND_CANNON, new int[]{GLFW.GLFW_KEY_V}));
                        }
                    } else {
                        NetworkHelper.toServerPlayer(new KeyInputPack(KeyInputPack.HAND_CANNON, new int[]{GLFW.GLFW_KEY_V}));
                    }

                    event.setCanceled(true);
                }
            }
        }
    }
}
